package sqlex

import (
	"strconv"
	"strings"
)

type OrderItem struct {
	Column            string   `json:"column,omitzero"`
	Asc               bool     `json:"asc,optional,omitzero"`
	CustomOrderValues []string `json:"customOrderValues,optional,omitzero"`
}

// OrderBy 生成mysql排序字符串
func (o *OrderItem) OrderBy() string {
	if len(o.CustomOrderValues) > 0 {
		return o.getCustomOrderValues()
	}
	if o.Asc {
		return o.Column + " ASC"
	}
	return o.Column + " DESC"
}

func (o *OrderItem) getCustomOrderValues() string {
	size := len(o.CustomOrderValues)
	builder := strings.Builder{}
	builder.WriteString(" CASE")
	for i, v := range o.CustomOrderValues {
		builder.WriteString(" WHEN " + o.Column + " = '" + v + "' THEN " + strconv.Itoa(i))
	}
	builder.WriteString(" ELSE " + strconv.Itoa(size) + " END ASC")
	return builder.String()
}

type Page struct {
	PageNo     int64       `json:"pageNo,optional,omitzero"`
	PageSize   int64       `json:"pageSize,optional,omitzero"`
	StartTime  int64       `json:"startTime,optional,omitzero"`
	EndTime    int64       `json:"endTime,optional,omitzero"`
	SortBy     []OrderItem `json:"sortBy,optional,omitzero"`
	IgnoreStat bool        `json:"ignoreStat,optional,omitzero"`
	IgnoreList bool        `json:"ignoreList,optional,omitzero"`
}

func (p *Page) OrderBy() string {
	size := len(p.SortBy)
	if size == 0 {
		return "order by id DESC"
	}

	order := "order by "
	for i, v := range p.SortBy {
		order = order + v.OrderBy()
		if size-1 != i {
			order = order + ","
		}
	}
	return order
}

// OrderByFieldMap 映射字段名
func (p *Page) OrderByFieldMap(fieldMap map[string]string) string {
	size := len(p.SortBy)
	if size == 0 {
		field := "id"
		if newField, ok := fieldMap[field]; ok {
			field = newField
		}
		return "order by " + field + " DESC"
	}

	order := "order by "
	for i, v := range p.SortBy {
		field := v.Column
		if newField, ok := fieldMap[field]; ok {
			field = newField
		}
		order = order + field + " "
		if !v.Asc {
			order = order + " DESC "
		}
		if size-1 != i {
			order = order + ","
		}
	}
	return order
}

func (p *Page) PageLimit() string {
	if p.PageNo == 0 {
		p.PageNo = 1
	}

	if p.PageSize == 0 {
		p.PageSize = 20
	}
	return "limit " + strconv.FormatInt((p.PageNo-1)*p.PageSize, 10) + "," + strconv.FormatInt(p.PageSize, 10)
}

func (p *Page) PageTimeRange(filed string) string {
	where := " where 1=1 "
	if p.StartTime > 0 {
		where += " and " + filed + " >= " + strconv.Itoa(int(p.StartTime))
	}
	if p.EndTime > 0 {
		where += " and " + filed + " < " + strconv.Itoa(int(p.EndTime))
	}
	return where
}
